package com.kim.logs.context;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.text.MessageFormat;

/**
 * @Deacription TODO
 * @Author jianhua.hong
 * @Date 2020/4/2 20:34
 **/
@Slf4j
@Aspect
public class ServiceLogHandler extends AbstractLogHandler {
    private static final String SERVICE_MESSAGE_FORMAT = "handle class=[{0}],handle method=[{1}],Param=[{2}],Response=[{3}],cost time=[{4}ms-({5})]";
    private static final String SERVICE_MESSAGE_ERROR_FORMAT = "handle class=[{0}],handle method=[{1}],Param=[{2}]";
    @Pointcut("@within(org.springframework.stereotype.Service) && execution(public * *(..))")
    public void servicePointcut() {

    }
    @Around("servicePointcut()")
    public Object doControllerAround(ProceedingJoinPoint point) throws Throwable {
        super.processRequestTraceId();
        String traceId = RequestLogContext.getTraceId();
        Long startTime = System.currentTimeMillis();
        String methodName = point.getSignature().getName();
        String className = point.getSignature().getDeclaringTypeName();
        Object[] params = point.getArgs();
        boolean outputLogMark = super.isOutPutLog(params);
        Object serviceResp = point.proceed();
        Long endTime = System.currentTimeMillis();
        Long costTime = endTime - startTime;
        if (outputLogMark) {
            String paramsStr = JSONObject.toJSONString(params, SerializerFeature.IgnoreNonFieldGetter);
            String rspStr = JSONObject.toJSONString(serviceResp, SerializerFeature.IgnoreNonFieldGetter);
            String timeFlag = getTimeCostFlag(costTime);
            Object[] paramsArray = new Object[]{
                    className, methodName, paramsStr, rspStr, costTime, timeFlag
            };
            log.info("[service-log-around-{}]{}", traceId, MessageFormat.format(SERVICE_MESSAGE_FORMAT, paramsArray));
            log.info("[times-log-{}] class=[{}],method=[{}],cost time=[{}-({})]", traceId, className, methodName, costTime, timeFlag);
        }
        return serviceResp;
    }
    @AfterThrowing(pointcut = "servicePointcut()", throwing = "e")
    public void handle(JoinPoint point, Exception e) {
        super.processRequestTraceId();
        String traceId = RequestLogContext.getTraceId();
        String methodName = point.getSignature().getName();
        String className = point.getSignature().getDeclaringTypeName();
        Object[] params = point.getArgs();
        String paramsStr = JSONObject.toJSONString(params, SerializerFeature.IgnoreNonFieldGetter);
        Object[] paramsArray = new Object[]{
                className, methodName, paramsStr
        };
        log.info("[service-log-pre-{}]{}", traceId, MessageFormat.format(SERVICE_MESSAGE_ERROR_FORMAT, paramsArray));
        log.info("[service-log-after-{}],handle class=[{}],handle method=[{}]异常", traceId, className, methodName);

    }
}
